package com.basker.pisces.tools.web;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.basker.pisces.core.datasource.IDataSourceManager;
import com.basker.pisces.core.io.TempFileSystemResource;
import com.basker.pisces.core.meta.IDataObjectMeta;
import com.basker.pisces.core.meta.bean.BeanMetaManager;
import com.basker.pisces.core.meta.bean.BeanMetaTypeWrapperRegistrar.BeanMetaTypeWrapper;
import com.basker.pisces.orm.data.meta.DataSetMeta;
import com.basker.pisces.orm.database.DatabaseDefinitionSqlGenerator;
import com.basker.pisces.service.annotation.IgnoreLoginContext;

@ConditionalOnClass(DatabaseDefinitionSqlGenerator.class)
@RestController
@RequestMapping("/t/sql")
public class SqlGenerateRestController {

    private static final String NO_SQL = "No sql generated!";

    @Autowired(required = false)
    private List<BeanMetaTypeWrapper> beanMetaTypeWrappers;

    @Autowired
    private IDataSourceManager dataSourceManager;

    @GetMapping(value = "/all", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    @IgnoreLoginContext
    public Resource exportSql() throws IOException {
        return this.exportSql("");
    }

    @GetMapping(value = "/{schema}/all", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    @IgnoreLoginContext
    public Resource exportSql(@PathVariable(name = "schema", required = false) String schema) throws IOException {
        if (CollectionUtils.isEmpty(beanMetaTypeWrappers)) {
            return new ByteArrayResource(NO_SQL.getBytes(StandardCharsets.UTF_8));
        }

        if (StringUtils.isEmpty(schema)) {
            schema = dataSourceManager.getDefaultDataSourceName();
        }

        File tempFile = null;

        try {
            TempFileSystemResource tempFileResource = new TempFileSystemResource(schema, "sql");
            tempFile = tempFileResource.getFile();

            generate2File(schema, tempFile);

            return tempFileResource;
        } finally {
            if (tempFile != null) {
                tempFile.deleteOnExit();
            }
        }

    }

    private void generate2File(String schema, File tempFile) {
        String defaultDataSourceName = dataSourceManager.getDefaultDataSourceName();
        List<BeanMetaTypeWrapper> wrappers = BeanMetaTypeWrapper.findBySchema(beanMetaTypeWrappers, schema,
                defaultDataSourceName);

        Set<String> schemaTemp = new HashSet<>();

        for (BeanMetaTypeWrapper wrapper : wrappers) {
            Class<?> beanType = wrapper.getBeanType();
            IDataObjectMeta objectMeta = BeanMetaManager.getBeanMeta(beanType);

            DataSetMeta dataSetMeta = DataSetMeta.create(objectMeta);
            DatabaseDefinitionSqlGenerator databaseDefinitionSqlGenerator = new DatabaseDefinitionSqlGenerator(
                    dataSetMeta);

            // 生成schema的sql，一个scheme只需生成一次
            if (!schemaTemp.contains(dataSetMeta.getSchema())) {
                databaseDefinitionSqlGenerator.generateSchemaSql2File(tempFile, true);
                schemaTemp.add(dataSetMeta.getSchema());
            }

            databaseDefinitionSqlGenerator.generateTableSql2File(tempFile, true);
        }
    }

}
